package com.triones.api.service.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.triones.api.entity.*;
import com.triones.api.entity.bo.LeptageQuoteBO;
import com.triones.api.entity.param.GlobalAccountParams;
import com.triones.api.entity.param.TotalBalanceRequestParams;
import com.triones.api.entity.param.WalletSingleParams;
import com.triones.api.entity.vo.*;
import com.triones.api.mapper.*;
import com.triones.api.service.CryptoWalletService;
import com.triones.api.service.GlobalAccountService;
import com.triones.api.service.third.LeptageService;
import com.triones.api.service.third.PhotonPayService;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 全球账户 -业务实现
 */
@Service
@RequiredArgsConstructor
public class GlobalAccountServiceImpl implements GlobalAccountService {

    private final LeptageGlobalAccountMapper leptageGlobalAccountMapper;

    private final CryptoBillDetailMapper cryptoBillDetailMapper;

    private final CryptoTransferMapper cryptoTransferMapper;

    private final CryptoExchangeMapper cryptoExchangeMapper;

    private final PhotonPayGlobalAccountMapper photonPayGlobalAccountMapper;

    private final PhotonPayService photonPayService;

    private final CryptoWalletService cryptoWalletService;

    private final LeptageService leptageService;

//    @Override
//    public TableDataInfo<GlobalAccountEntryVO> entryPageList(GlobalAccountParams globalAccountParams, PageQuery pageQuery) {
//        Map<String, Object> params = globalAccountParams.getParams();
//        LoginUser loginUser = LoginHelper.getLoginUser();
//        if (loginUser == null) {
//            throw new ServiceException("当前用户退出登录!");
//        }
//        LambdaQueryWrapper<GlobalAccountEntryDO> lqw = new LambdaQueryWrapper<GlobalAccountEntryDO>();
//        lqw.and(StringUtils.isNotEmpty(globalAccountParams.getCreditCurrency()),w ->
//            w.like(GlobalAccountEntryDO::getPayerName,globalAccountParams.getPayer()).or()
//            .like(GlobalAccountEntryDO::getPayerAccount,globalAccountParams.getPayer())
//        ).like(StringUtils.isNotEmpty(globalAccountParams.getFeeCurrency()),GlobalAccountEntryDO::getFeeCurrency,globalAccountParams.getFeeCurrency())
//         .like(StringUtils.isNotEmpty(globalAccountParams.getSettlementNo()),GlobalAccountEntryDO::getSettlementNo,globalAccountParams.getSettlementNo())
//         .like(StringUtils.isNotEmpty(globalAccountParams.getCreditCurrency()),GlobalAccountEntryDO::getCreditCurrency,globalAccountParams.getCreditCurrency())
//         .like(StringUtils.isNotEmpty(globalAccountParams.getSettlementCurrency()),GlobalAccountEntryDO::getSettlementCurrency,globalAccountParams.getSettlementCurrency())
//         .eq(StringUtils.isNotEmpty(globalAccountParams.getSettlementStatus()),GlobalAccountEntryDO::getSettlementStatus,globalAccountParams.getSettlementStatus());
//
//        if (params.get("beginTime") != null && params.get("endTime") != null) {
//            lqw.apply("UNIX_TIMESTAMP(REPLACE(created_at, 'T', ' ')) BETWEEN {0} and {1}", params.get("beginTime"),params.get("endTime"));
//        }
//        if (params.get("beginSettlement") != null && params.get("endSettlement") != null) {
//            lqw.apply("UNIX_TIMESTAMP(REPLACE(settlement_at, 'T', ' ')) BETWEEN {0} and {1}", params.get("beginSettlement"),params.get("endSettlement"));
//        }
//        lqw.orderByDesc(GlobalAccountEntryDO::getCreatedAt);
//        Page<GlobalAccountEntryVO> result = globalAccountEntryMapper.selectVoPage(pageQuery.build(), lqw);
//        return TableDataInfo.build(result);
//    }

    @Override
    public List<LeptageGlobalAccountVO> leptageList(String ccy) {
        /**
         * 刷新
         */
        try {
            List<Map> mapList = leptageService.totalBalance(null);
            if (mapList != null) {
                for (Map map : mapList) {
                    leptageGlobalAccountMapper.update(null,new LambdaUpdateWrapper<LeptageGlobalAccountDO>()
                        .set(LeptageGlobalAccountDO::getAmount, Convert.toStr(map.get("amount")))
                        .set(LeptageGlobalAccountDO::getUpdateTime, System.currentTimeMillis())
                        .eq(LeptageGlobalAccountDO::getCurrency, Convert.toStr(map.get("ccy"))));
                }
            }
        } catch (Exception e) {
            System.out.println(" 日志记录异常捕获 ");
        }
        LambdaQueryWrapper<LeptageGlobalAccountDO> lqw = new LambdaQueryWrapper<LeptageGlobalAccountDO>();
        return leptageGlobalAccountMapper.selectVoList(lqw);
    }

    @Override
    public TableDataInfo<CryptoSysBillVO> withdrawPageList(CryptoSysBillDO dto, PageQuery pageQuery) {
        LambdaQueryWrapper<CryptoSysBillDO> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(dto.getRequestId()), CryptoSysBillDO::getRequestId, dto.getRequestId())
            .eq(StringUtils.isNotBlank(dto.getStatus()), CryptoSysBillDO::getStatus, dto.getStatus())
            .eq(StringUtils.isNotBlank(dto.getWithdrawalMoneyCcy()), CryptoSysBillDO::getWithdrawalMoneyCcy, dto.getWithdrawalMoneyCcy())
            .eq(StringUtils.isNotBlank(dto.getPayoutMoneyCcy()), CryptoSysBillDO::getPayoutMoneyCcy, dto.getPayoutMoneyCcy())
            .eq(StringUtils.isNotBlank(dto.getFeeMoneyCcy()), CryptoSysBillDO::getFeeMoneyCcy, dto.getFeeMoneyCcy());
        Page<CryptoSysBillVO> result = cryptoBillDetailMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<CryptoTransferVO> transferPageList(CryptoTransferDO dto, PageQuery pageQuery) {
        LambdaQueryWrapper<CryptoTransferDO> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(dto.getRequestId()), CryptoTransferDO::getRequestId, dto.getRequestId())
            .eq(StringUtils.isNotBlank(dto.getDirection()), CryptoTransferDO::getDirection, dto.getDirection())
            .eq(StringUtils.isNotBlank(dto.getCcy()), CryptoTransferDO::getCcy, dto.getCcy())
            .eq(StringUtils.isNotBlank(dto.getChain()), CryptoTransferDO::getChain, dto.getChain())
            .eq(StringUtils.isNotBlank(dto.getStatus()), CryptoTransferDO::getStatus, dto.getStatus());
        Page<CryptoTransferVO> result = cryptoTransferMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<CryptoExchangeVO> exchangePageList(CryptoExchangeDO dto, PageQuery pageQuery) {
        LambdaQueryWrapper<CryptoExchangeDO> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(dto.getCcyPair()), CryptoExchangeDO::getCcyPair, dto.getCcyPair())
            .eq(StringUtils.isNotBlank(dto.getTxnId()), CryptoExchangeDO::getTxnId, dto.getTxnId())
            .eq(StringUtils.isNotBlank(dto.getStatus()), CryptoExchangeDO::getStatus, dto.getStatus());
        Page<CryptoExchangeVO> result = cryptoExchangeMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 更新累计金额
     */
    @Async
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateCumulativeAmount(BigDecimal amount) {
        //阈值
        BigDecimal threshold = new BigDecimal(5000.00);
        PhotonPayGlobalAccountDO globalAccountDO = photonPayGlobalAccountMapper.selectOne(new LambdaQueryWrapper<PhotonPayGlobalAccountDO>()
            .eq(PhotonPayGlobalAccountDO::getCurrency, "USD")
            .eq(PhotonPayGlobalAccountDO::getAccountType, "FT10001")
            .last("limit 1"));
        if (globalAccountDO != null) {
            globalAccountDO.setCumulativeAmount(globalAccountDO.getCumulativeAmount().add(amount));
            photonPayGlobalAccountMapper.updateById(globalAccountDO);

            /**
             * 阈值检测
             */
            if (globalAccountDO.getCumulativeAmount().subtract(globalAccountDO.getRealTimeBalance()).compareTo(threshold) == -1) {
                this.updateRealTimeBalance();
            }
        } else {
            this.updateRealTimeBalance();
        }
    }

    @Override
    public void updateRealTimeBalance() {
        //阈值
        BigDecimal threshold = new BigDecimal(5000.00);
        BigDecimal realTimeBalance = BigDecimal.ZERO;
        WalletSingleParams params = new WalletSingleParams();
        params.setCurrency("USD");
        params.setAccountType("FT10001");
        Map map = photonPayService.walletSingle(params);
        if (map != null) {
            realTimeBalance = Convert.toBigDecimal(map.get("realTimeBalance"));
            PhotonPayGlobalAccountDO globalAccountDO = photonPayGlobalAccountMapper.selectOne(new LambdaQueryWrapper<PhotonPayGlobalAccountDO>()
                .eq(PhotonPayGlobalAccountDO::getCurrency, "USD")
                .eq(PhotonPayGlobalAccountDO::getAccountType, "FT10001")
                .last("limit 1"));
            if (globalAccountDO != null) {
                globalAccountDO.setRealTimeBalance(realTimeBalance);
                globalAccountDO.setReturnedAt(Convert.toStr(map.get("returnedAt")));
                globalAccountDO.setUpdateAt(System.currentTimeMillis());
                globalAccountDO.setCumulativeAmount(BigDecimal.ZERO);
                photonPayGlobalAccountMapper.updateById(globalAccountDO);
            } else {
                globalAccountDO = new PhotonPayGlobalAccountDO();
                globalAccountDO.setMemberId(Convert.toStr(map.get("memberId")));
                globalAccountDO.setAccountNo(Convert.toStr(map.get("accountNo")));
                globalAccountDO.setAccountType(Convert.toStr(map.get("accountType")));
                globalAccountDO.setCurrency(Convert.toStr(map.get("currency")));
                globalAccountDO.setRealTimeBalance(realTimeBalance);
                globalAccountDO.setReturnedAt(Convert.toStr(map.get("returnedAt")));
                globalAccountDO.setCumulativeAmount(BigDecimal.ZERO);
                globalAccountDO.setUpdateAt(System.currentTimeMillis());
                photonPayGlobalAccountMapper.insert(globalAccountDO);
            }

            /**
             * 可用余额已经低于阈值（条件触发lpt提现）
             */
            if (realTimeBalance.compareTo(threshold) == -1) {
                List<LeptageGlobalAccountDO> leptageGlobalAccountList = leptageGlobalAccountMapper.selectList(
                    new LambdaQueryWrapper<LeptageGlobalAccountDO>().in(LeptageGlobalAccountDO::getCurrency, "USDT", "USDC"));
                if (leptageGlobalAccountList.size() > 0) {
                    for (LeptageGlobalAccountDO leptageGlobalAccountDO : leptageGlobalAccountList) {
                        if (leptageGlobalAccountDO.getCumulativeAmount().compareTo(BigDecimal.ZERO) == 1) {
                            // 系统询价
                            LeptageQuoteBO bo = new LeptageQuoteBO();
                            bo.setQuoteObj("sys");
                            bo.setSellCcy(leptageGlobalAccountDO.getCurrency());
                            bo.setTargetCcy("USD");
                            LeptageQuoteDO leptageQuoteDO = cryptoWalletService.leptageQuote(bo);
                            if (leptageQuoteDO != null) {
                                // 换汇
                                String ccyPair = leptageGlobalAccountDO.getCurrency() + "-" + "USD";
                                cryptoWalletService.exchange(ccyPair, Convert.toStr(leptageGlobalAccountDO.getCumulativeAmount()), leptageQuoteDO.getId());
                                // 置空累计金额
                                leptageGlobalAccountDO.setCumulativeAmount(BigDecimal.ZERO);
                                leptageGlobalAccountMapper.updateById(leptageGlobalAccountDO);
                            }
                        }
                    }
                }
                // 合并提现
                TotalBalanceRequestParams balanceRequestParams = new TotalBalanceRequestParams();
                balanceRequestParams.setCcy("USD");
                List<Map> mapList = leptageService.totalBalance(balanceRequestParams);
                if (mapList.size() > 0) {
                    for (Map map1 : mapList) {
                        if ("USD".equals(map1.get("ccy"))) {
                            BigDecimal amount = Convert.toBigDecimal(map1.get("amount"));
                            if (amount.compareTo(BigDecimal.ZERO) == 1) {
                                // 创建提现交易
                                cryptoWalletService.sysWithdraw("USD", "USD", Convert.toStr(amount));
                            }
                        }
                    }
                }
            }
        }
    }
}
